CountDownTimer
CountDownTimer是android sdk中os包下的一个辅助抽象类,这个类通过handler来实现一个倒计时的操作。在倒计时期间会定期调用用户实现的回调函数。
比如一个简单的使用场景:一个30秒倒计时
1 2 3 4 5 6 7 8 9
| new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) { mTextField.setText("seconds remaining: " + millisUntilFinished / 1000); } public void onFinish() { mTextField.setText("done!"); } }.start();
|
onTick方法对这个对象来说是同步的,当onTick方法的实现花费的时间和倒计时的间隔来说需要很久的时候,调用onTick也是按照顺序发生的,方法不会在之前的回调完成之前发生。
1 2 3 4 5 6 7
| private long mStopTimeInFuture;
* 是否取消 */ private boolean mCancelled = false;
|
CountDownTime的构造函数,millisInFuture从调用start方法开始直到倒计时结束的毫秒时间,countDownInterval 接收onTick回调的时间间隔
1 2 3 4
| public CountDownTimer(long millisInFuture, long countDownInterval) { mMillisInFuture = millisInFuture; mCountdownInterval = countDownInterval; }
|
取消倒计时
1 2 3 4 5
| private static final int MSG = 1; public synchronized final void cancel() { mCancelled = true; mHandler.removeMessages(MSG); }
|
开始倒计时
1 2 3 4 5 6 7 8 9 10
| public synchronized final CountDownTimer start() { mCancelled = false; if (mMillisInFuture <= 0) { onFinish(); return this; } mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; mHandler.sendMessage(mHandler.obtainMessage(MSG)); return this; }
|
定期执行的回调,使用的时候需要实现这个方法,millisUntilFinished参数表示剩余时间
1
| public abstract void onTick(long millisUntilFinished);
|
当倒计时结束的时候的回调
1
| public abstract void onFinish();
|
处理倒计时的handler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| private Handler mHandler = new Handler() {
@Override public void handleMessage(Message msg) {
synchronized (CountDownTimer.this) { if (mCancelled) { return; }
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) { onFinish(); } else if (millisLeft < mCountdownInterval) { sendMessageDelayed(obtainMessage(MSG), millisLeft); } else { long lastTickStart = SystemClock.elapsedRealtime(); onTick(millisLeft);
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay); } } } };
|
通过源码可知,CountDownTimer采用的是handler机制,通过sendMessageDelayed延迟发送一条message到主线程的looper中,然后在自身中收到之后判断剩余时间,并发出相关回调,然后再次发出message的方式。之前实现这种倒计时是通过asynctask,在线程中通过Thread.sleep来实现,通过asyntask的cancel来实现取消,通过构造asynctask传入接口的实现来onTick的类似功能。这个CountDownTimer默认是在当前looper当中,可以是在UI线程也可以是在非UI线程中执行,如果在UI线程中执行,那是不是会稍微加重UI线程的负担?